package com.zsj.Array;


import java.util.Arrays;
import java.util.Iterator;
import java.util.Spliterator;
import java.util.function.Consumer;
import java.util.stream.IntStream;

/**
 * @author zsj
 * @date 2023/10/20 18:09
 * 动态数组
 */
public class DynamicArray implements Iterable<Integer> {

    private int size = 0;//逻辑大小 类似与当前索引

    private int capacity = 8;//容量

    //懒加载
    private int[] array = {}; //默认初始化数组

    public DynamicArray() {

    }

    /**
     * 添加元素到末尾
     *
     * @param element 添加的元素
     */
    public void addLast(int element) {
        add(size, element);
    }

    /**
     * 插入指定索引位置的值(不是覆盖)
     *
     * @param index   索引
     * @param element 元素
     */
    public void add(int index, int element) {
        //需要判断是否扩容
        checkAndGrow();
        //边界条件 插入的索引位置不能为负数并且不能大于数组的逻辑大小
        if (index >= 0 && index < size) {
            System.arraycopy(array, index,
                    array, index + 1, size - index);
        }
        array[index] = element;
        size++;
    }

    /**
     * 校验是否扩容以及扩容
     */
    private void checkAndGrow() {
        if (size == 0) {
            //如果是刚开始就初始化数组为我们的初识容量
            array = new int[capacity];
        } else if (size == capacity) {
            //否则判断是否扩容并且执行对应逻辑
            capacity += capacity >> 1;
            int[] newArray = new int[capacity];
            System.arraycopy(array, 0, newArray, 0, size);
            array = newArray;
        }
    }


    /**
     * 获取指定索引的元素
     * @param index 索引位置
     * @return 数组索引元素
     */
    public int get(int index) {
        return array[index];
    }


    /**
     * 获取当前逻辑大小
     *
     * @return 逻辑大小
     */
    public int size() {
        return this.size;
    }


    public void forEachMyself(Consumer<Integer> consumer) {
        for (int i = 0; i < size; i++) {
            consumer.accept(array[i]);
        }
    }


    /**
     * 迭代器遍历
     *
     * @return 返回迭代器
     */
    @Override
    public Iterator<Integer> iterator() {
        return new Iterator<Integer>() {
            int i = 0;//迭代器初始位置索引

            @Override
            public boolean hasNext() {//判断是否含有下一位
                return i < size;
            }

            @Override
            public Integer next() {//返回当前元素 并且指针前移
                return array[i++];
            }
        };
    }

    /**
     * 函数式接口遍历
     *
     * @param action Consumer接口
     */
    @Override
    public void forEach(Consumer<? super Integer> action) {
        Iterable.super.forEach(action);
    }

    @Override
    public Spliterator<Integer> spliterator() {
        return Iterable.super.spliterator();
    }

    /**
     * 获取流对象
     *
     * @return 当前数组的流对象
     */
    public IntStream stream() {
        //此size是不包含的 所以不用-1
        return IntStream.of(Arrays.copyOfRange(array, 0, size));
    }

    /**
     * 删除指定索引位置的元素
     *
     * @param index 指定索引
     * @return 删除的元素索引 -1为删除失败
     */
    public int remove(int index) {
        if (check(index)) {
            int deleted = array[index];
            //不是最后一个的时候在使用arraycopy 要不然没必要 直接将size--就可以;
            if (index < size - 1) {
            /*
            要移动的数组
            移动的起使索引位置
            移动到哪个目标数组
            目标数组的起使位置
            移动几个元素到目标数组
             */
                System.arraycopy(array, index + 1,
                        array, index, size - index - 1);

            }
            size--;
            return deleted;
        }
        return -1;
    }

    /**
     * 校验索引是否合法
     *
     * @param index 传入索引
     * @return true合法 false不合法
     */
    private boolean check(int index) {
        return index >= 0 && index < size;
    }


}
